/*
 * This program is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 3 of the License, or 
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License along 
 * with this program; if not, write to the Free Software Foundation, Inc., 
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef _POSTWIDGET_H
#define _POSTWIDGET_H

#include <QWidget>
#include <QTextDocument>
#include <QTextEdit>
#include <QPaintEvent>
#include <QPixmapCache>
#include <QLabel>
#include <QTimer>
#include "components/board.h"
#include "components/post.h"
#include "postdocument.h"
#include "components/threadptr.h"
#include "poststyle.h"
#include "postwidgetelement.h"

using namespace Wishmaster; // FIXME UDOLIL!!!!!!!1111
class PostItemView;
class PostWidget : public QWidget
{
	Q_OBJECT
public:
	PostWidget(Wishmaster::Board* b, const ThreadId& threadid, const PostId& postid, PostItemView* parent = 0,
			   bool hideImages = false, const PostStylePtr& style = PostStylePtr());
	virtual ~PostWidget();

	void setText(Wishmaster::PostPtr post);
	QString text();

	void setPostId(const PostId& id);
	PostId postId();

	void setThreadId(const ThreadId& id);
	ThreadId threadId();

	void setBoard(Wishmaster::Board* b);
	Wishmaster::Board* board();

	void setWidth(int w);

	void update();
	void recalcGeometry();

	PostItemView* piv();
	void setPiv(PostItemView* piv);

	QString linkAt(const QPoint& p);
	QString selectedText(const QPoint& p);

	PostWidget* popup(const QPoint& p);

	void setChainLeader(bool cl);
	bool isChainLeader();

	void resetText();
	void resetSelection();

	void setImageHideMode(bool s);
	bool isImageHideMode();

	void setPostStyle(const PostStylePtr& style);
	PostStylePtr postStyle() const;
signals:
	void postDelete(const PostId& postId);
	void postHide(const PostId& postId);
	void postIdClicked(const PostId& postId);
	void postLinkClicked(const PostId& postId);
	void postDownloadAttachment(const PostId& postId, int index);
	void linkClicked(const QString& url);

	void signalMouseLeft();
	void signalMouseEnter();

protected:
	virtual void paintEvent(QPaintEvent* event);
	void mouseMove(const QPoint& p, const QPoint& global);
	void mouseLeft();
	void mousePress(const QPoint& p);
	void mouseClick(const QPoint& p);
	void help(const QPoint& p, const QPoint& global);
	void doPaint(QPainter* painter, const QRect& originalRect);
	virtual void mouseMoveEvent(QMouseEvent* event);
	virtual void mousePressEvent(QMouseEvent* event);
	virtual void mouseReleaseEvent(QMouseEvent* event);
	virtual bool event(QEvent* event);
	void calculateGeometries(QSize size);
	QPixmap makePixmap(const QSize& optrect);
	int headerWidth();
	void adjustWidth();
	QString headerText();
	void updateFont();
	void enterEvent(QEvent* ev);
	void leaveEvent(QEvent* ev);

protected slots:
	void deletePopup();
	void popupMouseLeft();
	void popupMouseEnter();

private:
	PostItemView* m_piv;
	PostDocument m_document;
	QTextCursor m_selection;
	bool m_sel;
	int m_xynta;

	typedef enum
	{
		pweUnknown = 0,
		pweDelete,
		pweHide,
		pweUnhide,
		pwePostId,
		pweReferenceCount,
		pweReferenceList,
		pweInfo,
		pweTimestamp
	} tPostWidgetElement;

	int m_activeElement;
	QRect m_referenceListRect;

	Wishmaster::Board* m_board;
	Wishmaster::ThreadPtr m_thread;
	ThreadId m_threadId;
	PostId m_postId;
	QString m_postName;
	QString m_postTopic;
	QString m_popupLink;

	PostWidget* m_popup;
	bool m_popupChanged;
	QTimer m_popupDeleteTimer;

	PostStylePtr m_postStyle;

	QList<PostWidgetElementPtr> m_elements;
	QRect m_textRect;
	int m_headerWidth;
	bool m_chainLeader;
	bool m_inMMEvent; // FIXME fucking hack
	bool m_imageHideMode;

	QPixmapCache::Key m_key;

	static const int ContentMargin = 2;
	static const int HeaderSpacing = 16;
	static const int ReplyListWidth = 100;

	static const int PopupTimeout = 1000;

	friend class PostItemDelegate;
	friend class PostItemView;
};

#endif

